package com.bac.rentmap.ad.flat.proccess;

import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import org.springframework.beans.factory.annotation.Required;

import com.bac.rentmap.ad.flat.FlatAd;
import com.bac.rentmap.ad.flat.GeoLocation;
import com.bac.rentmap.jdo.JdoSupport;
import com.bac.rentmap.manager.BuildingManager;
import com.bac.rentmap.model.Building;
import com.google.appengine.api.datastore.GeoPt;

/**
 * Populates {{lat}}, {{lon}} or {{geoLocationStatus}}.
 *
 * @author Andrew Osipenko
 */
public class GeoLocationFlatAdProccessor extends JdoSupport implements
        FlatAdProccessor {
    private static final Logger log = Logger
            .getLogger(GeoLocationFlatAdProccessor.class.getName());

    private int batchSize;
    private BuildingManager buildingManager;

    @SuppressWarnings("unchecked")
    public int proccess() {
        PersistenceManager persistenceManager = getPersistenceManager();
        try {
            Query query = buildQuery(persistenceManager);
            query.setRange(0, batchSize);
            List<FlatAd> flatAds = (List<FlatAd>) query.execute();
            log.fine("Found " + flatAds.size() + " ads");
            for (FlatAd flatAd : flatAds) {
                Integer buildingNumber = flatAd.getBuilding();
                if (buildingNumber != null) {
                    Building building = buildingManager.findBuilding(flatAd
                            .getCity(), flatAd.getLocalAddress());
                    if (building != null) {
                        GeoPt geoPt = building.getGeoPt();
                        flatAd.setGeoLocation(new GeoLocation((double) geoPt
                                .getLatitude(), (double) geoPt.getLongitude()));
                    } else {
                        log.info("Can't find building geo location for "
                                + flatAd.getStreet() + ", "
                                + flatAd.getBuilding());
                        flatAd.setGeoLocationError();
                    }
                }
            }
            return flatAds.size();
        } finally {
            persistenceManager.close();
        }
    }

    @Required
    public void setBatchSize(int batchSize) {
        this.batchSize = batchSize;
    }

    @Required
    public void setBuildingManager(BuildingManager buildingManager) {
        this.buildingManager = buildingManager;
    }

    public int getQueueSize() {
        PersistenceManager persistenceManager = getPersistenceManager();
        try {
            Query query = buildQuery(persistenceManager);
            query.setResult("count(this)");
            Object res = query.execute();
            if(res == null)
                return 0;
            return ((Number)res).intValue();
        }
        finally{
            persistenceManager.close();
        }
    }

    private Query buildQuery(PersistenceManager persistenceManager) {
        Query query = persistenceManager.newQuery(FlatAd.class);
        query
                .setFilter("geoLocationStatus == '"
                        + FlatAd.STATUS_NOT_CALCULATED
                        + "' && buildingDefined == true && ratingCalculated == true");
        return query;
    }

    public int getBatchSize() {
        return batchSize;
    }
}
